﻿using DnsClient.Internal;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Logging;

using MQTTnet.AspNetCore;
using MQTTnet.Protocol;
using MQTTnet.Server;

namespace ThingsGateway.Application.Core
{
    public static class MqttConfiguration
    {
        public static void ConfigureMqttServer(this KestrelServerOptions option)
        {
            var config = App.GetConfig<MqttServerSettings>("MqttServer", false);
            option.ListenAnyIP(config.Port, config => config.UseMqtt());
        }

        public static void UseMqttServer(this IApplicationBuilder app, MqttController mqttController)
        {
            app.UseMqttServer(mqttServer =>
            {
                mqttServer.ValidatingConnectionAsync += mqttController.ValidateConnection;
                mqttServer.ClientConnectedAsync += mqttController.OnClientConnected;
            });

            app.UseEndpoints(endpoint =>
            {
                endpoint.MapConnectionHandler<MqttConnectionHandler>(
    "/mqtt",
    httpConnectionDispatcherOptions =>
    {
        httpConnectionDispatcherOptions.WebSockets.SubProtocolSelector =
                  protocolList => protocolList.FirstOrDefault() ?? string.Empty;
    }
    );
            });
        }

        public static void AddMqttService(
            this IServiceCollection services)
        {
            var config = App.GetConfig<MqttServerSettings>("MqttServer", false);
            services.AddHostedMqttServerWithServices(options =>
            {
                options.WithDefaultEndpointPort(config.Port).WithDefaultEndpoint();
            });
            services.AddMqttConnectionHandler();
            services.AddMqttWebSocketServerAdapter();
            services.AddMqttTcpServerAdapter();
            services.AddConnections();
        }

    }
    public sealed class MqttController
    {
        private ILogger<MqttController> _logger;
        private ISqlSugarClient _sysConfigRep;
        public MqttController(ILogger<MqttController> logger, IServiceScopeFactory scopeFactory)
        {
            _logger = logger;

            var scope = scopeFactory.CreateScope();
            var services = scope.ServiceProvider;

            _sysConfigRep = services.GetService<SqlSugarRepository<SysConfig>>().Context;
        }

        public Task OnClientConnected(ClientConnectedEventArgs eventArgs)
        {
            if (eventArgs.ClientId.ToUpper() == "THINGSGATEWAYVUE3")
                return Task.CompletedTask;
            _logger.LogInformation($"Mqtt客户端 '{eventArgs.ClientId}' 连接成功.");
            return Task.CompletedTask;
        }


        public async Task ValidateConnection(ValidatingConnectionEventArgs e)
        {
            var password = await GetConfig<string>(CommonConst.MqttPassword);
            var username = await GetConfig<string>(CommonConst.MqttUserName);
            if (e.ClientId.ToUpper() == "THINGSGATEWAYVUE3")
            {
                if (e.UserName == username && e.Password == password)
                    return;//前端信息不输出日志
            }

            if (e.UserName != username)
            {
                e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
            }

            if (e.Password != password)
            {
                e.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
            }
            _logger.LogInformation($"Mqtt客户端 '{e.ClientId}' 连接，结果：{e.ReasonCode}");

            async Task<T> GetConfig<T>(string code)
            {
                var config = await _sysConfigRep.Queryable<SysConfig>().FirstAsync(u => u.Code == code);
                var value = config != null ? config.Value : default;
                return (T)Convert.ChangeType(value, typeof(T));
            }
        }
    }
}
